#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

/*
使用： 注册SIGSEGV处理函数_signal_handler1 或 2，程序出错时打得到pc指针
再反汇编 csky-linux-objdump  -S out.elf  > mybin.s
找到对应的指令地址，注意因为CPU流水线的问题，PC指针可能提前读指，比如实际出错地址= PC -8
*/
static void _signal_handler1(int sig,siginfo_t *info,void *ctx)
{
#include <ucontext.h>    
	int i;
	ucontext_t *context=(ucontext_t*)ctx;
	//void *p_buf[256];
	//char **p_strs;
	//int i,nptrs;
	printf("signal=%d memory location=%p  si_errno:%d si_pid:%d si_uid:%d\n",
			sig,info->si_addr,info->si_errno,info->si_pid,info->si_uid);
	printf("pc:%lx sc_sr:%lx\n",context->uc_mcontext.sc_pc,context->uc_mcontext.sc_sr);
	printf("r0:%lx\n",context->uc_mcontext.sc_a0);
	printf("r1:%lx\n",context->uc_mcontext.sc_a1);
	printf("r2:%lx\n",context->uc_mcontext.sc_a2);
	printf("r3:%lx\n",context->uc_mcontext.sc_a3);
	for( i = 0; i < 10 ; i++){
		printf("sc_regs-%d:%lx\n",i,context->uc_mcontext.sc_regs[i]);
	}
	printf("r15:%lx\n",context->uc_mcontext.sc_r15);
	
}

static void _signal_handler2(int sig,siginfo_t *info,void *ctx)
{
#include <ucontext.h>
#include <execinfo.h>
    ucontext_t *context=(ucontext_t*)ctx;
    void *p_buf[256];
    char**p_strs;
    int i,nptrs;
    printf("signal=%d memory location=%p\n",sig,info->si_addr);
    nptrs = backtrace(p_buf,256);
    p_strs = backtrace_symbols(p_buf,nptrs);
    if(p_strs == NULL){
        perror("symbols err");
        exit(-1);
    }
    for(i=0;i<nptrs;i++){
        printf(" [%02d] %s\n",i,p_strs[i]);
    }
    free(p_strs);
}

void os_set_coredump(void) {
	struct sigaction action;
	sigemptyset(&action.sa_mask);
	action.sa_sigaction = _signal_handler;
	action.sa_flags = SA_SIGINFO;
	sigaction(SIGSEGV,&action,NULL);
}


static void test3(int*p)
{
	*p =1 ;
}
static void test2(int*p)
{
	test3(p);
}
static void test1(int*p)
{
	test2(p);
}
int main(int argc,char*argv[])
{
	int *p=0x12345678;
	os_set_coredump();
	test1(p);
	return 0;
}
